package com.example.video.controller;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.example.video.Enum.videoStatus;
import com.example.video.common.Result;
import com.example.video.entity.*;
import com.example.video.service.*;
import com.example.video.util.DeviceEncode;
import com.example.video.util.TimeUtil;
import com.example.video.util.laixiOperate.Operate;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/device")
public class DeviceController {
    @Resource
    private IAccountService accountService;
    @Resource
    private IVideoService videoService;
    @Resource
    private IDeviceService deviceService;

    @Resource
    private IVideoLogService videoLogService;
    @Resource
    private IOuterAccountService outerAccountService;

    @Resource
    private Operate laixiOperate;

    /**
     * 若接口改变，相应Operate的createDevice也需要改变
     * @param id
     * @return
     */
    @GetMapping("/getDeviceId")
    public ResponseEntity<ByteArrayResource> getHelloWorldFile(@RequestParam("id") String id) {
        // 创建一个字节数组资源
        ByteArrayResource resource = new ByteArrayResource(id.getBytes(StandardCharsets.UTF_8));

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\""+id+".txt\"")
                .contentType(MediaType.TEXT_PLAIN)
                .contentLength(resource.contentLength())
                .body(resource);
    }

    @PostMapping("/upload/videoStatusErr")
    public Result<String> uploadVideoStatusErr(@RequestParam String deviceId, @RequestParam Integer videoId, @RequestParam String name) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        Result<String> rs = new Result<>();
        String errArr = "";
        rs.setCode(0);
        log.info("DeviceController -> uploadVideoStatusErr -> msg: id = " + deviceId + " videoId = " + videoId + " name = " + name);
        name = name.replace(".js", "");
        Video video = Db.lambdaQuery(Video.class)
                .eq(Video::getId, videoId)
                .select(Video::getPublishErr, Video::getId)
                .one()
        ;
        if(video == null){
            log.info("DeviceController -> uploadVideoStatusErr -> msg: video is null");
        }else{
            errArr = video.getPublishErr();
        }
        if(errArr == null || "".equals(errArr)){
            errArr = name;
        }else{
            errArr = errArr + "," + name;
        }
        log.info("DeviceController -> uploadVideoStatusErr -> msg: errArr = "+errArr);
        Db.lambdaUpdate(Video.class)
                .eq(Video::getId, videoId)
                .set(Video::getPublishErr, errArr)
                .update()
        ;
        return rs;
    }


    /**
     * 更新视频状态为已下载
     * @param deviceId 设备id
     * @param videoId 视频id
     * @return
     */
    @PostMapping("/upload/videoStatus")
    public Result<String> uploadVideoStatus(@RequestParam String deviceId, @RequestParam Integer videoId, @RequestParam String status) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        log.info("DeviceController -> uploadVideoDownload -> msg: id = " + deviceId + " videoId = " + videoId + " status = " + status);
        Result<String> rs = new Result<>();
        Video video = videoService.getItem(videoId);
        Integer flag = video.getStatus();
        if("download".equals(status)){
            flag = videoStatus.DEVICEDOWN.getStatus();
        }else if ("upload".equals(status)){
            flag = videoStatus.DEVICEUPLOAD.getStatus();
        }
        if (video == null) {
            rs.setCode(-1);
            rs.setMsg("错误：没有该id的资源信息！");
            rs.setData(null);
            rs.setCount(0);
        } else {
            if (accountService.getItem(video.getAccountId()).getDeviceId().equals(deviceId)) {

                if (videoService.updateStatusByid(videoId, flag)) {
                    rs.setCode(0);
                    rs.setMsg("更新成功！");
                    rs.setData(null);
                    rs.setCount(0);
                } else {
                    rs.setCode(-1);
                    rs.setMsg("错误：服务器端更新错误！");
                    rs.setData(null);
                    rs.setCount(0);
                }
            } else {
                rs.setCode(-1);
                rs.setMsg("错误：该设备id与资源id不匹配！");
                rs.setData(null);
                rs.setCount(0);
            }
        }
        return rs;
    }

    /**
     * 设备绑定完成后请求的接口
     *
     * @param deviceId 设备id
     * @param status   设备状态，一般为 1
     * @return （暂无）
     * @TODO 将设备的状态进行更新、将设备移入指定分组
     */
    @PostMapping("/upload/bindStatus")
    public Result<Boolean> uploadStatus(@RequestParam String deviceId, @RequestParam(defaultValue = "1") Integer status) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        Result<Boolean> rs = new Result<>();
        rs.setData(true);
        log.info("DeviceCon -> upload/status -> status: " + deviceId + " " + " status = " + status);
        log.info("DeviceCon -> upload/status -> status: " + deviceId + " " + " deviceId = " + deviceId);
        // 发送转移分组命令
        Account account = accountService.getItemByDeviceId(deviceId);
        String groupId = Db.lambdaQuery(User.class)
                .select(User::getGroupId)
//                .eq(User::getRole, account.getRole())
                .list()
                .get(0)
                .getGroupId();
//        log.info("DeviceCon -> upload/status -> user: " );
        Result<String> operateRes = null;
        try {
            operateRes = laixiOperate.moveDeviceToGroup(groupId, List.of(deviceId));
        } catch (URISyntaxException | InterruptedException e) {
            log.info("DeviceCon -> upload/status -> 来喜服务连接失败！" + e);
        }

        // 更新状态
        if(operateRes.getCode() == 0){
            Db.lambdaUpdate(Device.class)
                    .eq(Device::getDeviceId, deviceId)
                    .set(Device::getStatus, status)
                    .update()
            ;
            rs.setCode(0);
            rs.setMsg("成功！");
        }else{
            rs.setCode(-1);
            rs.setMsg("转移设备分组失败！");
        }

        return rs;
    }

    /**
     * 设备上传错误消息接口
     *
     * @param deviceId   设备id
     * @param createTime 错误消息创建时间
     * @param msg        错误信息
     * @return 是否成功
     */
    @PostMapping("/upload/errMsg")
    public Result<Boolean> uploadErrMsg(@RequestParam String deviceId, @RequestParam String createTime, @RequestParam String msg, @RequestParam(defaultValue = "0") Integer videoId) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        Result<Boolean> rs = new Result<>();
        log.info("DeviceCon -> upload/errMsg -> msg: " + deviceId + " " +videoId + " " + createTime + " " + msg);
        VideoLog videoLog = new VideoLog();
        videoLog.setId(0);
        videoLog.setVideoId(videoId);
        videoLog.setMessage(msg);
        videoLog.setUpData(TimeUtil.StrToDate(createTime));
        videoLog.setDeviceId(deviceId);
        videoLogService.save(videoLog);
        return rs;
    }

    /**
     * 查询设备
     * @deprecated
     * @param page  页
     * @param limit 每页大小
     * @return 设备信息
     * @TODO：添加权限条件
     */
    @ResponseBody
    @PostMapping("/deviceList")
    public Result<List<Device>> getDevicesList(Integer page, Integer limit) {

        Result<List<Device>> rs = new Result<>();
        List<Device> list = deviceService.getList(page, limit);
        if (list.isEmpty()) {
            rs.setCode(-1);
            rs.setData(null);
            rs.setMsg("获取失败！");
        } else {
            rs.setCode(0);
            rs.setData(list);
            rs.setMsg("获取成功！");
        }
        rs.setCount(deviceService.GetCount());
        return rs;
    }

    @PostMapping("/get/outer")
    public Result<List<OuterAccount>> getOuterAccount(@RequestParam String deviceId) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        Result<List<OuterAccount>> rs = new Result<>();
        Account account = accountService.getItemByDeviceId(deviceId);
        log.info("DevCtr -> /get/outer ->msg: id = "+deviceId);
        log.info("DevCtr -> /get/outer ->msg: account = "+account);
        List<OuterAccount> list = outerAccountService.getListByAccountId(account.getId());
        log.info("DevCtr -> /get/outer ->msg: list = " + list);
        if (list.isEmpty()) {
            rs.setCode(-1);
            rs.setData(null);
            rs.setMsg("获取失败！");
            rs.setCount(0);
        } else {
            rs.setCode(0);
            rs.setData(list);
            rs.setMsg("获取成功！");
            rs.setCount(list.size());
        }
        return rs;
    }


    /**
     * 查询是否有新视频
     *
     * @param deviceId 设备id
     * @return
     */
    @PostMapping("/get/data")
    public Result<Video> status(@RequestParam String deviceId) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        Result<Video> rs = new Result<>();
        //查该设备ID对应的Account
        log.info("DeviceController -> /get/data -> msg: id = " + deviceId);
        Account account = accountService.selectOne(deviceId);
        //如果没查到，代表没绑定
        if (account == null) {

            rs.setData(null);
            rs.setMsg("该deviceId尚未记录于系统中，请先绑定Account");
            return rs;
        }
        //查到了

        //就根据Account的ID返回对应的Video的ID集合

        Video item = videoService.getItemByAccountIdAndStatus(account.getId(), videoStatus.UPLOADABLE);
        if (item == null) {
            rs.setCode(-1);
            rs.setCount(0);
            rs.setMsg("无数据！");
            rs.setData(null);
        } else {
            rs.setCode(0);
            rs.setCount(1);
            rs.setMsg("查找成功");
            rs.setData(item);
        }
        return rs;
    }


    /*
     ************************
     *        暂时无用       *
     ************************
     */

    /**
     * 设备初始化
     *
     * @param deviceId 设备ID（暂定），使用 device.fingerprint 获取。
     * @return OK（暂定）
     */
    @PostMapping("/init")
    public Result<List<OuterAccount>> init(String deviceId) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        log.info("DeviceController -> init -> msg: " + deviceId);
        // TODO：保存到数据库-device，和需要与设备关联的。如outer
        // 绑定成功后返回绑定账号对应的外部账号集合
        return accountService.bind(deviceId);
    }

    /**
     * 设备查询绑定状态
     *
     * @param deviceId 设备id
     * @return
     */
    @PostMapping("/get/bindStatus")
    public Result<Account> getBindStatus(String deviceId) {
        deviceId = DeviceEncode.decodeFileName(deviceId);
        log.info("DeviceController -> getBindStatus -> msg: " + deviceId);
        // TODO：查询数据库-device，获取绑定状态
        Account account = accountService.selectOne(deviceId);
        Result<Account> rs = new Result<>();
        if (account == null) {
            rs.setCode(-1);
            rs.setMsg("该deviceId尚未记录于系统中，请先绑定Account");
            rs.setData(null);
            rs.setCount(0);

        } else {
            rs.setCode(0);
            rs.setMsg("查询成功，已绑定！");
            rs.setData(account);
            rs.setCount(0);

        }

        return rs;
    }






}
